﻿namespace Dropthings.Test.Rules
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;

    using Microsoft.VisualStudio.TestTools.WebTesting;
    public class FormElement
    {
        public string ControlFullID { get; set; }
        public string ControlValue { get; set; }
        public ControlCategory ControlCategory { get; set; }

        public string TempProperty { get; set; }

        public override string ToString()
        {
            return ControlFullID;
        }
    }
    [DisplayName("Extract Form Elements")]
    public class ExtractFormElements : ExtractionRule
    {
        #region Fields

        public const string FORM_ELEMENT_KEYS = "$FORM_ELEMENTS";
        public const string INPUT_PREFIX = "$INPUT.";
        public const string SELECT_PREFIX = "$SELECT.";


        private static Regex _FindInputTags = new Regex(
            @"<(input)\s*[^>]*(name)=""(?<name>([^""]*))""\s*[^>]*",
            RegexOptions.IgnoreCase
            | RegexOptions.Multiline
            | RegexOptions.IgnorePatternWhitespace
            | RegexOptions.Compiled
            );

        private static Regex _FindSelectTags = new Regex(
            @"<select[^>]*>(.*?)</select>",
            RegexOptions.IgnoreCase
            | RegexOptions.Singleline
            | RegexOptions.IgnorePatternWhitespace
            | RegexOptions.Compiled
            );

        private static Regex _ExtractSelectTags = new Regex(
            @"<select\s*[^>]*name=""(?<name>([^""]*))""\s*[^>]*.*<option\s"
            + @"*[^>]*\s*[^>]*value=""(?<value>([^""]*))""",
            RegexOptions.IgnoreCase
            | RegexOptions.Singleline
            | RegexOptions.IgnorePatternWhitespace
            | RegexOptions.Compiled
            );

        #endregion Fields

        #region Methods

        public static List<FormElement> Extract(string bodyString)
        {
            List<FormElement> formElements = new List<FormElement>();
            var processMatches = new Action<MatchCollection, ControlCategory>((extractMatches, controlCategory) =>
            {
                foreach (Match extractMatch in extractMatches)
                {
                    ControlCategory recheckedControlCategory = controlCategory;
                    if (extractMatch.Value.Contains("type=\"hidden\""))
                    {
                        recheckedControlCategory = ControlCategory.HIDDEN;
                    }

                    string fullControlID = extractMatch.Groups["name"].Value;
                    string controlValue = extractMatch.Groups["value"].Value;

                    int controlValueStartIndex = extractMatch.Value.IndexOf("value=\"") + "value=\"".Length;
                    if (string.IsNullOrEmpty(controlValue) && controlValueStartIndex > "value=\"".Length)
                    {
                        int controlValueEndIndex = extractMatch.Value.IndexOf("\"", controlValueStartIndex);
                        controlValue = extractMatch.Value.Substring(controlValueStartIndex, controlValueEndIndex - controlValueStartIndex);
                    }

                    formElements.Add(new FormElement()
                    {
                         ControlFullID = fullControlID,
                         ControlValue = controlValue
                    });

                }

            });

            var inputMatches = _FindInputTags.Matches(bodyString);
            processMatches(inputMatches, ControlCategory.INPUT);

            foreach (Match match in _FindSelectTags.Matches(bodyString))
            {
                var extractMatches = _ExtractSelectTags.Matches(match.Value);
                processMatches(extractMatches, ControlCategory.SELECT);
            }
            return formElements;
           
        }

        public override void Extract(object sender, ExtractionEventArgs e)
        {
            var formElements = Extract(e.Response.BodyString);

            foreach (var element in formElements)
            {
                RuleHelper.PlaceIDSelector(e.WebTest.Context, element.ControlFullID, element.ControlValue);
                RuleHelper.PlaceIndexSelector(e.WebTest.Context, element.ControlCategory, element.ControlFullID, element.ControlValue);
            }
        }

        #endregion Methods
    }
}